package mypazar.cartagoseagent;

import jason.environment.grid.Location;
import mypazar.agent.PersonAgent;
import mypazar.jenamodel.PazarVocabulary;
import tr.edu.ege.seagent.planner.htn.Action;
import tr.edu.ege.seagent.planner.htn.ExecutionMethod;
import tr.edu.ege.seagent.planner.htn.Outcome;
import cartago.ArtifactId;
import cartago.CartagoException;
import cartago.Op;
import cartago.Tuple;
import cartago.util.agent.CartagoBasicContext;
import cartago.util.agent.Percept;

import com.hp.hpl.jena.datatypes.xsd.XSDDatatype;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.ResourceFactory;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.rdf.model.StmtIterator;

/**
 * Action class of ACCheckProduct.
 */
public class ACCheckProduct extends Action {

	/**
	 * Ctx outcome.
	 */
	@Outcome
	private CartagoBasicContext Ctx;

	/**
	 * Returns the value of the Ctx outcome.
	 */
	public CartagoBasicContext getCtx() {
		return this.Ctx;
	}

	/**
	 * Sets the value of the Ctx outcome.
	 */
	public void setCtx(CartagoBasicContext Ctx) {
		this.Ctx = Ctx;
	}

	/**
	 * ArtifactId outcome.
	 */
	@Outcome
	private ArtifactId ArtifactId;

	/**
	 * Returns the value of the ArtifactId outcome.
	 */
	public ArtifactId getArtifactId() {
		return this.ArtifactId;
	}

	/**
	 * Sets the value of the ArtifactId outcome.
	 */
	public void setArtifactId(ArtifactId ArtifactId) {
		this.ArtifactId = ArtifactId;
	}

	/**
	 * Execution method.
	 */
	@ExecutionMethod
	public void execute() {
		Model beliefBase = (Model) getHeapValue(PersonAgent.BELIEF_BASE_ITEM_NAME);

		String PERSON_URI = PazarVocabulary.NS_URI
				+ getAgentIdentifier().toString().substring(0, 7);

		Resource resPerson = beliefBase.getResource(PERSON_URI);

		Location currentLoc = getCurrentLoc(resPerson);

		// Set that stall as seen and return related salesman's name
		String stallArtifactName = "Stall"
				+ setAsSeenAndGetSmanName(beliefBase, PERSON_URI, currentLoc)
						.substring(8, 9);

		ArtifactId artifactId = null;
		CartagoBasicContext ctX = (CartagoBasicContext) getHeapValue(PazarVocabulary.CTX_PERSON_ITEM_NAME);

		try {
			artifactId = ctX.lookupArtifact(stallArtifactName);
			ctX.focus(artifactId);
		} catch (CartagoException e) {
			e.printStackTrace();
		}

		// Get product that person want to buy
		String productName = getProductName(beliefBase, PERSON_URI);

		try {
			ctX.doAction(artifactId, new Op("checkProduct", productName));
		} catch (CartagoException e) {
			e.printStackTrace();
		}

		Percept percept = null;

		boolean related = false;
		boolean notrelated = false;

		// Wait for percept and receive relatedProduct signal
		while (true) {
			try {
				percept = ctX.waitForPercept();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			Tuple signal = percept.getSignal();
			if (signal.getLabel().equals("relatedProduct")) {
				boolean checkrelated = (Boolean) signal.getContent(0);
				if (checkrelated) {
					related = true;
				} else {
					notrelated = true;
				}
			}
			// if any signal has received, stop the while loop
			if (related || notrelated) {
				break;
			}
		}

		if (related) {
			this.setCtx(ctX);
			this.setArtifactId(artifactId);
			this.setOutcomeState("Inform");
		} else {
			this.setOutcomeState("Failure");
		}
	}

	/**
	 * Gets agent's current location from belief base
	 * 
	 * @param beliefBase
	 * @param personURI
	 * @return
	 */
	private Location getCurrentLoc(Resource resPerson) {
		StmtIterator iterPos = resPerson.listProperties(ResourceFactory
				.createProperty(PazarVocabulary.POSITION_URI));
		if (iterPos.hasNext()) {
			Statement stmtPersonPos = iterPos.next();
			Resource resPersonStall = stmtPersonPos.getObject().asResource();
			// gets and returns location from given resource
			return getResLocation(resPersonStall);

		} else
			return null;
	}

	/**
	 * Gets given resource's location
	 * 
	 * @param resPersonStall
	 * @return
	 */
	private Location getResLocation(Resource resPersonStall) {
		// gets and returns location from given iteration
		return new Location(resPersonStall
				.getProperty(
						ResourceFactory
								.createProperty(PazarVocabulary.POS_X_URI))
				.getLiteral().getInt(), resPersonStall
				.getProperty(
						ResourceFactory
								.createProperty(PazarVocabulary.POS_Y_URI))
				.getLiteral().getInt());
	}

	/**
	 * Sets stall that located agent's current location as seen stall
	 * 
	 * @param beliefBase
	 * @param personURI
	 * @param currentLoc
	 * @return
	 */
	public String setAsSeenAndGetSmanName(Model beliefBase, String personURI,
			Location currentLoc) {
		Resource resPerson = beliefBase.getResource(personURI);

		StmtIterator iterStall = resPerson.listProperties(ResourceFactory
				.createProperty(PazarVocabulary.STALL_URI));
		while (iterStall.hasNext()) {
			Statement stmtPersonStall = iterStall.next();
			Resource resPersonStall = stmtPersonStall.getObject().asResource();

			if (currentLoc.equals(getResLocation(resPersonStall))) {
				resPersonStall.addProperty(beliefBase
						.createProperty(PazarVocabulary.STALL_SEEN_URI),
						PersonAgent.YES_STR, XSDDatatype.XSDstring);

				return resPersonStall
						.getProperty(
								ResourceFactory
										.createProperty(PazarVocabulary.HAS_SALESMAN_URI))
						.getLiteral().getString();
			}
		}
		return null;
	}

	/**
	 * Gets product name from belief base
	 * 
	 * @param beliefBase
	 * @param personURI
	 * @return
	 */
	private String getProductName(Model beliefBase, String personURI) {
		String pName = null;
		Resource resPerson = beliefBase.getResource(personURI);
		StmtIterator iterProduct = resPerson.listProperties(ResourceFactory
				.createProperty(PazarVocabulary.PRODUCT_URI));
		if (iterProduct.hasNext()) {
			Statement stmtProduct = iterProduct.next();
			Resource resProduct = stmtProduct.getObject().asResource();

			pName = resProduct
					.getProperty(
							ResourceFactory
									.createProperty(PazarVocabulary.PRODUCT_NAME_URI))
					.getLiteral().getString();
		}
		return pName;
	}

}
